﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;

namespace SimpleORM
{
    public class IDObject : CDObject
    {
        #region Properties

        public virtual Guid ID { get; set; }

        #endregion

        #region Ctor

        public IDObject()
        {
            ID = Guid.NewGuid();
        }

        #endregion
    }
    [Serializable]
    public class NameableIDObject : IDObject, IComparable
    {
        #region Properties

        public virtual string Name { get; set; }

        #endregion

        #region Methods

        public override string ToString()
        {
            return Name;
        }

        public virtual int CompareTo(object obj)
        {
            NameableIDObject objName = obj as NameableIDObject;
            if (objName == null)
                return 0;

            return Name.CompareTo(objName.Name);
        }

        public override void Dispose()
        {
            base.Dispose();

            Name = null;
        }

        #endregion
    }
    public abstract class Provider : NameableIDObject, IProvider
    {
        #region Properties

        public string ConnectionString { get; protected set; }

        #endregion

        #region Fields

        #region Fields - Static

        private static Hashtable htProviders;

        #endregion

        #endregion

        #region Ctor

        static Provider()
        {
            InstallProviders();
        }

        public Provider(string cntString)
        {
            ConnectionString = cntString;
            OnInitializeComponent(ConnectionString);
        }

        #endregion

        #region Methods

        #region Methods - Public

        public Exception Test()
        {
            lock (this)
                return OnTest();
        }

        #endregion

        #region Methods - Virtual

        #region Methods - Virtual - Initialize

        protected virtual void OnInitializeComponent(string cntString)
        {
        }

        #endregion

        #region Methods - Virtual - Function

        protected virtual Exception OnTest()
        {
            return null;
        }

        #endregion

        #endregion

        #region Methods - Override

        public override object Clone()
        {
            var provider = (Provider)Activator.CreateInstance(
                this.GetType(), new object[] { ConnectionString });
            provider.Name = Name;

            return provider;
        }

        public override void Dispose()
        {
            base.Dispose();

            ConnectionString = null;
        }

        #endregion

        #region Methods - Static

        #region Methods - Static - Public

        public static IProvider Create(string cntStringName)
        {
            ConnectionStringSettings css = ConfigurationManager.ConnectionStrings[cntStringName];
            IProvider provider = Create(css.ProviderName, css.ConnectionString);

            return provider;
        }

        public static T Create<T>(string cntStringName) where T : IProvider
        {
            return (T)Create(cntStringName);
        }

        [Obsolete]
        public static IProvider Create(string cntStringName, string cntString, string providerName)
        {
            return Create(providerName, cntString);
        }

        public static T Create<T>(string providerName, string cntString) where T : IProvider
        {
            return (T)Create(providerName, cntString);
        }

        public static IProvider Create(string providerName, string cntString)
        {
            Type type = Get(providerName);
            if (type == null) throw new KeyNotFoundException("providerName");

            Provider value = (Provider)Activator.CreateInstance(type, new object[] { cntString });
            value.Name = providerName;

            return value;
        }

        #endregion

        #region Methods - Static - Private

        private static void InstallProviders()
        {
            htProviders = new Hashtable();
            InstallDefaultProviders();

            //ProviderSettings cfg = ProviderSettings.GetContext();
            //if (cfg == null)
            //{
            //    //Tracker.WriteLine(new TrackerObject
            //    //{
            //    //    EventID = EdProvider.langLoadProviderContextFail,
            //    //    Grade = eMessageGrade.Warn,
            //    //    Description = new EdProvider().GetName(EdProvider.langLoadProviderContextFail),
            //    //    Source = typeof(Provider).FullName,
            //    //});

            //    return;
            //}
            //foreach (ProviderElement pe in cfg.Providers)
            //    Register(pe.Name, Type.GetType(pe.Type, true));
        }

        private static void InstallDefaultProviders()
        {
            Register("System.Data.SqlClient", typeof(ProviderDbCSQLServer));
        }

        private static void Register(string name, Type type)
        {
            lock (htProviders)
                htProviders[name] = type;
        }

        private static Type Get(string name)
        {
            lock (htProviders)
            {
                if (string.IsNullOrEmpty(name))
                {
                    foreach (var item in htProviders.Values)
                    {
                        return item as Type;
                    }
                }
                return htProviders[name] as Type;
            }
        }

        #endregion

        #endregion

        #endregion
    }
}
